package com.fit.exercise.msgp2p;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

public class Util {

	public static String filePath = "friend.data";

	private static File createIfNotExit(String filePath) throws IOException {
		File file = new File(filePath);
		if (!file.exists())
			file.createNewFile();
		return file;
	}

	/**
	 * Read all objects
	 * 
	 * @param filePath
	 * @return
	 * @throws Exception
	 */
	public static List<PersonInfo> readFromFile(String filePath)
			throws Exception {
		List<PersonInfo> personInfos = new ArrayList<>();
		File file = createIfNotExit(filePath);
		FileReader fr = new FileReader(file);
		BufferedReader br = new BufferedReader(fr);
		try {
			String line = "";

			do {
				line = br.readLine();
				if (line != null && !line.isEmpty()) {
					personInfos.add(new PersonInfo(line));
				}
			} while (line != null && !line.isEmpty());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (br != null)
				br.close();
		}

		return personInfos;
	}

	/**
	 * Save an object to file
	 * 
	 * @param filePath
	 * @param obj
	 * @throws IOException
	 */
	public static void saveToFile(String filePath, PersonInfo obj)
			throws IOException {
		File file = createIfNotExit(filePath);
		FileWriter fw = new FileWriter(file, true);
		BufferedWriter bw = new BufferedWriter(fw);
		try {
			bw.write(obj.toString());
			bw.newLine();
		} catch (Exception e) {
			throw e;
		} finally {
			if (bw != null)
				bw.close();
		}
	}

	/**
	 * Save a list PersonalInfo to file
	 * 
	 * @param filePath
	 * @param personInfos
	 * @throws IOException
	 */
	public static void saveToFile(String filePath, List<PersonInfo> personInfos)
			throws IOException {

		File file = createIfNotExit(filePath);
		FileWriter fw = new FileWriter(file);
		BufferedWriter bw = new BufferedWriter(fw);
		try {
			for (PersonInfo personInfo : personInfos) {
				bw.write(personInfo.toString());
				bw.newLine();
			}
		} catch (Exception e) {
			throw e;
		} finally {
			if (bw != null)
				bw.close();
		}

	}

	/**
	 * 
	 * @param person
	 * @param personInfos
	 * @return 0: not exist; 1: name is exist; 2: ipAddress & port is exist;
	 */
	public static int checkPersonExist(PersonInfo person,
			List<PersonInfo> personInfos) {
		for (PersonInfo personInfo : personInfos) {
			if (personInfo.getName().equalsIgnoreCase(person.getName())) {
				return 1;
			} else if (personInfo.getIpAddress().equalsIgnoreCase(
					person.getIpAddress())
					&& personInfo.getPort().compareTo(person.getPort()) == 0) {
				return 2;
			}
		}
		return 0;
	}

	public static boolean isNameExist(String name, List<PersonInfo> personInfos) {
		for (PersonInfo personInfo : personInfos) {
			if (personInfo.getName().equalsIgnoreCase(name)) {
				return true;
			}
		}
		return false;
	}

	public static PersonInfo findByIpAndPort(String ip, Integer port,
			List<PersonInfo> personInfos) {
		PersonInfo result = null;
		for (PersonInfo personInfo : personInfos) {
			if (personInfo.getIpAddress().equalsIgnoreCase(ip)
					&& port.compareTo(personInfo.getPort()) == 0) {
				result = personInfo;
			}
		}

		if (result == null) {
			result = new PersonInfo(ip + ":" + port, ip, port);
		}

		return result;
	}

	public static <T> byte[] convertToByteArray(T object) throws IOException {

		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ObjectOutputStream outputStream = new ObjectOutputStream(baos);
		outputStream.writeObject(object);

		return baos.toByteArray();
	}

	@SuppressWarnings("unchecked")
	public static <T> T convertFromByteArray(byte[] data) throws IOException,
			ClassNotFoundException {
		ByteArrayInputStream bais = new ByteArrayInputStream(data);
		ObjectInputStream ois = new ObjectInputStream(bais);
		return (T) ois.readObject();
	}
	
	public static void main(String[] args) {

		try {
			List<PersonInfo> personInfos = readFromFile(filePath);

			List<PersonInfo> list = convertFromByteArray(convertToByteArray(personInfos));
			for (PersonInfo personInfo : list) {
				System.out.println(personInfo.getName());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
